//
//  LoginMethodServcie().swift
//  ezyform
//
//  Created by Moennig Q on 21/7/2022.
//  Copyright © 2022 Client.Solution Pty Ltd. All rights reserved.
//

import Foundation
import LocalAuthentication
import UIKit
enum BiometryType : Int {
    case none
    case touchID
    case faceID
    case gesture
}
class LoginMethodServcie {
    //获取当前设备支持Face id还是Touch id（Face id或Touch id不一定开启）
    func getSupportedBiometryType() -> BiometryType{
        //该参数必须在canEvaluatePolicy方法后才有值
        let authContent = LAContext()
        var error: NSError?
        if authContent.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {//此方法是在设备系统设置中已经设置了指纹或face id信息才会返回
            //iPhoneX出厂最低系统版本号：iOS11.0.0
            if authContent.biometryType == .faceID {
                return .faceID
            }else if authContent.biometryType == .touchID {
                return .touchID
            }
        }else{//这个是在设备系统设置中没有设置了指纹或face id，但是authContent.biometryType会返回相应的支持信息
            if authContent.biometryType == .faceID {
                return .faceID
            }else if authContent.biometryType == .touchID {
                return .touchID
            }
        }
        return .none
    }
    //获取当前可用的生物识别是Touch ID还是Face ID，或者两者都没有设置
    func getUsefulBiometryType() -> (BiometryType, LAError.Code?){
        //该参数必须在canEvaluatePolicy方法后才有值
        let authContent = LAContext()
        var error: NSError?
        var errorCode: LAError.Code?
        var biometryType: BiometryType = .none
//        authContent.localizedCancelTitle = "Enter Username/Password"
        if authContent.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
            //iPhoneX出厂最低系统版本号：iOS11.0.0
            if authContent.biometryType == .faceID {
                biometryType = .faceID
            }else if authContent.biometryType == .touchID {
                biometryType = .touchID
            }
        }else{
            guard let laError = error as? LAError else{
              return (.none, nil)
            }
            errorCode = laError.code
        }
        return (biometryType, errorCode)
    }
    func getlocalizedReasonBySupportBiometryType()->String {
        let supportType = self.getSupportedBiometryType()
        if supportType == .touchID {
            return "Press Home Button to Verify"
        }else if supportType == .faceID {
            return "Verify with facial recognition"
        }
        return ""
    }
    func userLocalAuth(block :@escaping (Bool,LAError.Code?, Error?)->(Void)){
        let authContent = LAContext()
        //如果为空不展示输入密码的按钮，只有一个cancel按钮
        authContent.localizedFallbackTitle = "Try another Login method"//点击此按钮，对应errorType 是userFallback
        var error: NSError?
        /*
         LAPolicy有2个参数：
         用TouchID/FaceID验证，如果连续出错则需要锁屏验证手机密码，
         但是很多app都是用这个参数，等需要输入密码解锁touchId&faceId再弃用该参数。
         优点：用户在单次使用后就可以取消验证。
         1，deviceOwnerAuthenticationWithBiometrics
         
         用TouchID/FaceID或密码验证, 默认是错误两次或锁定后, 弹出输入密码界面
         等错误次数过多验证被锁时启用该参数
         2，deviceOwnerAuthentication
         
         */
        if authContent.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
            authContent.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: self.getlocalizedReasonBySupportBiometryType()) {(success,error) in
                DispatchQueue.main.async {
                    if success {
                        //evaluatedPolicyDomainState 只有生物验证成功才会有值
                        //可本地记录此值，如果此值改变则表示生物信息是否变更
                        if let _ = authContent.evaluatedPolicyDomainState {
                            //如果不放在主线程回调可能会有5-6s的延迟
//                            print("验证成功")
                            block(true, nil,nil)
                        }
                    }else{
                        guard let laError = error as? LAError else{
//                            print("touchID不可用")
                            block(false, nil,nil)
                            return
                        }
                        block(false, laError.code,error)
                    }
                }
            }
        }else{
//            print("设备不支持或验证多次后被锁定")
            guard let laError = error as? LAError else{
//              print("touchID不可用")
                block(false, nil,nil)
                return
            }
            block(false,laError.code,error)
        }
    }
    //获取当前的登录方式
    func getCurrentLoginMethod()->LoginMethodOperation{
        //先检测生物识别是那种
        let (biometryType, _) = self.getUsefulBiometryType()
        //1.touch id
        if biometryType == .touchID {
            //1.先touch id
            let cacheKey = self.getCacheKey(.touchID)
            if let flag = UserDefaults.standard.value(forKey: cacheKey) as? Bool,flag {//开启了指纹识别
                return .touchID
            }
        }
        //3.face id
        if biometryType == .faceID {
            let cacheKey = self.getCacheKey(.faceID)
            if let flag = UserDefaults.standard.value(forKey: cacheKey) as? Bool,flag {//开启了脸部识别
                return .faceID
            }
        }
        //3.gesture
        let cacheKey = self.getCacheKey(.gesture)
        if let flag = UserDefaults.standard.value(forKey: cacheKey) as? Bool,flag {//开启了脸部识别
            return .gesture
        }
        return .password
    }
    //获取其他的已开启的登录方式
    func getOtherLoginMethod(_ currentLoginMethod: LoginMethodOperation)->[LoginMethodOperation]{
        var list = [LoginMethodOperation]()
        //先检测生物识别是那种
        let (biometryType, _) = self.getUsefulBiometryType()
        //显示排序是：password, gesture, touch id ,face id
        //1.pwd
        list.append(.password)
        //2.gesture
        let cacheKey = self.getCacheKey(.gesture)
        if let flag = UserDefaults.standard.value(forKey: cacheKey) as? Bool,flag {//开启了脸部识别
            list.append(.gesture)
        }
        //3.touch id
        if biometryType == .touchID {
            //1.先touch id
            let cacheKey = self.getCacheKey(.touchID)
            if let flag = UserDefaults.standard.value(forKey: cacheKey) as? Bool,flag {//开启了指纹识别
                list.append(.touchID)
            }
        }
        //4.face id
        if biometryType == .faceID {
            let cacheKey = self.getCacheKey(.faceID)
            if let flag = UserDefaults.standard.value(forKey: cacheKey) as? Bool,flag {//开启了脸部识别
                list.append(.faceID)
            }
        }
        //5.过滤掉当前的login method
        if let index = list.firstIndex(where: {$0 == currentLoginMethod}){
            list.remove(at: index)
        }
        return list
    }
    func getLoginMethodFlag(_ type: LoginMethodOperation)->Bool{
        let cacheKey = self.getCacheKey(type)
        if let flag = UserDefaults.standard.value(forKey: cacheKey) as? Bool, flag{
            return true
        }else{
            return false
        }
    }
    func getCacheKey(_ type: LoginMethodOperation)->String{
        return APPConfig.loginInfo.email + "-" + type.rawValue
    }
    func setLoginMethodFlag(_ type: LoginMethodOperation, isOn: Bool, result: String = ""){
        let cacheKey = self.getCacheKey(type)
        UserDefaults.standard.set(isOn, forKey: cacheKey)
        
        if type == .gesture, result != "" {
            //设置密码成功，保存手势密码
            let gesturePwdCacheKey = self.getCacheKey(.gestureSetting)
            UserDefaults.standard.set(result, forKey: gesturePwdCacheKey)
        }
        UserDefaults.standard.synchronize()
    }
    func dealTagArrayToStr(_ array: [Int])->String{
        let toStrList: [String] = array.map { "\($0)"}
        let resultPwd = toStrList.joined()
        return resultPwd
    }
    func initRootVC(){
        guard let window = Tool.getKeyWindow() else {
            return
        }
        //判断引导页是否显示过
        let showStarViewFlag: Bool = (Tool().getValueOfUserDefaults(key: APPConfig.ShowStartViewKey) as? Bool ?? false)
        
        if APPConfig.loginInfo.access_token != "" {
            if showStarViewFlag{//显示过引导页
                let cacheKey = LoginMethodServcie().getCacheKey(.loginMethodGuide)
                if let data = UserDefaults.standard.value(forKey: cacheKey) as? Bool, data {//显示过login method引导图
                    let tabbarVC = TabBarViewController()
                    window.rootViewController = tabbarVC
                }else{
                    UserDefaults.standard.set(true, forKey: cacheKey)
                    UserDefaults.standard.synchronize()
                    let vc = LoginMethodSettingViewController()
                    vc.isGuideFlag = true
                    let navVC = BaseNavigationController(rootViewController: vc)
                    window.rootViewController = navVC
                }
            }else{//跳转到引导页
                let vc = StartViewController()
                window.rootViewController = vc
            }
        }else{
            if showStarViewFlag{//显示过引导页
                let vc = LoginViewController()
                vc.autoToFavoriteLoginMethod = true
                let navVC = BaseNavigationController(rootViewController: vc)
                window.rootViewController = navVC
            }else{//跳转到引导页
                let vc = StartViewController()
                window.rootViewController = vc   
            }
        }
        ReachabilityHelper.shared.showNetworkStatusView()
    }
    func toCheckLogin(successClosure: @escaping (()->Void), faildClosure: @escaping  ((String,String)->Void)){
        let model = LoginInfoModel()
        model.email = APPConfig.loginInfo.email
        if let pwd = UserDefaults.standard.object(forKey: APPConfig.CachePasswordKey) as? String, pwd != ""{
            model.password = pwd
        }
        let viewModel = LoginService()
        viewModel.setBlockAfterNetwork({ (result , _) -> Void in
            ModelViewUtil.shared.hideLoadingView()
            successClosure()
        }) {(code, error) -> Void in
            ModelViewUtil.shared.hideLoadingView()
            faildClosure(code,error)
        }

        //add Loading view
        ModelViewUtil.shared.showLoadingView(NSLocalizedString("login.logining" , comment: ""))
        viewModel.login(model)
    }
    func getBiometryTypeName(_ biometryType: LoginMethodOperation)->String{
        var resultStr = ""
        if biometryType == .faceID {
            resultStr = "Face ID"
        }else if biometryType == .touchID {
            resultStr = "Touch ID"
        }
        return resultStr
    }
    deinit{
        DebugLog("LoginMethodServcie deinit")
    }
}
